////////////////////////////////////////////////////////////////////////////
//
//  Crytek Engine Source File.
//  Copyright (C), Crytek Studios, 2010.
// -------------------------------------------------------------------------
//  File name:   ThreadBackEnd.h
//  Version:     v1.00
//  Created:     07/05/2011 by Christopher Bolte
//  Compilers:   Visual Studio.NET
// -------------------------------------------------------------------------
//  History:
////////////////////////////////////////////////////////////////////////////

#ifndef THREAD_BACKEND_H_
#define THREAD_BACKEND_H_

#include <IJobManager.h>
#include "../SPUDriver/JobStructs.h"

namespace JobManager {
namespace ThreadBackEnd {
namespace detail {
	// stack size for backend worker threads
	enum { eStackSize = 256*1024 };

} // namespace detail
	// forward declarations
	class CThreadBackEnd;

	// class to represent a worker thread for the PC backend
	class CThreadBackEndWorkerThread: public CrySimpleThread<>
	{
		public:
//#ifdef CAFE			
//      CThreadBackEndWorkerThread(CrySemaphore &rSemaphore, JobManager::SJobQueue_ThreadBackEnd &rJobQueue, uint32 nId);
//#else
       CThreadBackEndWorkerThread(CryFastSemaphore &rSemaphore, JobManager::SJobQueue_ThreadBackEnd &rJobQueue, uint32 nId);
//#endif
			~CThreadBackEndWorkerThread();

			virtual void Run();
			virtual void Stop();
			
	private:
		void DoWork();
		void DoWorkProducerConsumerQueue(SInfoBlock &rInfoBlock);
		
		string																m_sThreadName;				// name of the worker thread		
		uint32																m_nId;								// id of the worker thread
		volatile bool													m_bStop;	
//#ifdef CAFE
//    CrySemaphore&										    	m_rSemaphore;
//#else
		CryFastSemaphore&											m_rSemaphore;
//#endif
		JobManager::SJobQueue_ThreadBackEnd&	m_rJobQueue;
	};

	// the implementation of the PC backend
	// has n-worker threads which use atomic operations to pull from the job queue
	// and uses a semaphore to signal the workers if there is work requiered
	class CThreadBackEnd : public IBackend
	{		
	public:
		CThreadBackEnd();
		virtual ~CThreadBackEnd();

		bool Init(uint32 nSysMaxWorker);
		bool ShutDown();
		void Update(){}

		virtual JobManager::EAddJobRes AddJob( JobManager::CJobDelegator& RESTRICT_REFERENCE crJob, const uint32 cOpMode, const JobManager::TJobHandle cJobHandle, JobManager::SInfoBlock &rInfoBlock );
		
		virtual uint32 GetNumWorkerThreads() const { return m_arrWorkerThreads.size(); }		
	private:
		friend class JobManager::CJobManager;

		JobManager::SJobQueue_ThreadBackEnd				m_JobQueue;						//SPU job queue node where jobs are pushed into and from
//#ifdef CAFE
//    CrySemaphore												    	m_Semaphore;
//#else
		CryFastSemaphore													m_Semaphore;					// semaphore to count available jobs, to allow the workers to go sleeping instead of spinning when no work is requiered
//#endif
		std::vector<CThreadBackEndWorkerThread*>	m_arrWorkerThreads;		// array of worker threads 
	};

} // namespace ThreadBackEnd
} // namespace JobManager
			

#endif // THREAD_BACKEND_H_